//Copyright (C) 2009 Ron Coleman. Contact: ronncoleman@gmail.com
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 3 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this library; if not, write to the Free Software
//Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

/*
 * GroundsFrame.java
 *
 * Created on Oct 22, 2009, 8:24:50 PM
 */
package org.workplicity.marist.grounds.ui;

import java.awt.event.MouseEvent;
import org.workplicity.marist.grounds.GroundsRequest;
import org.workplicity.marist.grounds.ui.table.RequestTableModel;
import org.workplicity.marist.grounds.util.CustomRenderer;
import org.workplicity.marist.grounds.worklet.GroundsWorklet;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.TableColumnModel;
import org.workplicity.entry.User;
import org.workplicity.entry.WorkRequest;
import org.workplicity.entry.WorkSlate;
import org.workplicity.entry.event.Event;
import org.workplicity.entry.event.Recurring;
import org.workplicity.marist.grounds.util.GroundsHelper;
import org.workplicity.marist.print.MainPrinter;
import org.workplicity.plugin.util.Host;
import org.workplicity.task.NetTask;
import org.workplicity.util.Helper;
import org.workplicity.util.Logger;
import org.workplicity.util.Resources;
import org.workplicity.util.WorkDate;
import org.workplicity.worklet.WorkletContext;
import java.util.Date;
import java.text.DateFormat;
//import java.util.logging.Logger;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

/**
 * This is the top-level class for interfacing with the user.
 * @author Ron Coleman
 */
public class GroundsFrame extends javax.swing.JFrame {

    private static GroundsFrame frame = null;
    private GroundsWorklet worklet = GroundsWorklet.getInstance();
    private WorkletContext context = worklet.getContext();
    private User user = null;
    private boolean allowPopups = false;

    /**
     * Constructor
     */
    public GroundsFrame() {
        initComponents();

        frame = this;

        user = Helper.whoAmI(context);

        this.setTitle("Netslate - Grounds (" + user.getLogname() + ")");

        this.setIconImage(Resources.logoSmall.getImage());

        configureTable();

        initToStart();

        checkChanges();
    }

    private void checkChanges() {
        if (user.getStamp() == null)
            return;

        ArrayList<WorkSlate> workSlates =
                GroundsHelper.getWorkSlates(user.getWorkSlateList());

        Logger.log("user '" + user + "' has " + workSlates.size() + " work slates");

        if (workSlates.isEmpty()) {
            return;
        }

        Logger.log("user stamp=" + new Date(user.getStamp().getTime()));

        String ws = "";
        for (WorkSlate workSlate : workSlates) {
            Logger.log("work slate '" + workSlate.getName() + "' update=" + new Date(workSlate.getUpdateDate().getTime()));

            if (user.getStamp().getTime() < workSlate.getUpdateDate().getTime()) {
                if (ws.length() != 0) {
                    ws += "\n";
                }

                ws += workSlate.getName();
            }
        }

        if (ws.length() != 0) {
            JOptionPane.showMessageDialog(frame, "Changes found in work slate(s) of yours:\n" + ws,
                    "Grounds", JOptionPane.INFORMATION_MESSAGE);
        }

        allowPopups = true;

        loadOrders(allowPopups);

        return;
    }

    private void configureTable() {
        TableColumnModel cm = this.requestTable.getColumnModel();

        CustomRenderer cr = new CustomRenderer();

        for (int i = 0; i < requestTable.getColumnCount(); i++) {
            cm.getColumn(i).setCellRenderer(cr);
        }

    }

    private void initToStart() {
        // Set 24 hours are the default age
        this.ageComboBox.setSelectedIndex(0);

        // If user is not super, disable reassign and delete buttons
        if (!Helper.isSuperUser(context)) {
//            this.reassignMenuItem.setEnabled(false);
            this.deleteButton.setEnabled(false);
        }

        // If user is super, allow them to view OPEN requests
        if (Helper.isSuperUser(context)) {
            this.statusComboBox.addItem(WorkRequest.Status.OPEN);
        }

        // Allow other users to view rest but PENDING, RECURRING, and CLOSED
        this.statusComboBox.addItem(WorkRequest.Status.DISPATCHED);
        this.statusComboBox.addItem(WorkRequest.Status.STARTED);
        this.statusComboBox.addItem(WorkRequest.Status.HOLD);
        this.statusComboBox.addItem(WorkRequest.Status.FINISHED);

        // If user is super, allow them to view PENDING, RECURRING, and CLOSED
        if (Helper.isSuperUser(context)) {
            this.statusComboBox.addItem(WorkRequest.Status.PENDING);
            this.statusComboBox.addItem(WorkRequest.Status.RECURRING);
            this.statusComboBox.addItem(WorkRequest.Status.CLOSED);
        }

        // Set the default status on opening the dialog
        this.statusComboBox.setSelectedItem(WorkRequest.Status.DISPATCHED);

        // Refresh the caches
        worklet.getServicesCache().refresh();

        worklet.getWorkSlatesCache().refresh();

        worklet.getUsersCache().refresh();

        // Fill out the user combo box with "me" as the selected default
        User me = (User) worklet.getContext().read(Resources.TAG_USER);

        for (User auser : worklet.getUsersCache().getCache()) {
            this.userComboBox.addItem(auser);

            if (auser.getId().equals(me.getId())) {
                me = auser;
            }
        }

        this.userComboBox.setSelectedItem(me);

        // Turn-off visibility to other users work requests unless we're super
        if (!Helper.isSuperUser(context)) {
            this.userComboBox.setEnabled(false);
        }

//        // Load the requests
//        loadOrders(false);

        // Add mouse support for the request table
        // See http://mycodepage.blogspot.com/2006/09/how-to-create-double-click-event-on.html
        requestTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    JTable target = (JTable) e.getSource();
                    int row = target.getSelectedRow();
                    //int column = target.getSelectedColumn();
                    editRequest(row);
                }
            }
        });
    }

    private void loadOrders(boolean interact) {
        // Set the table to filter orders 
        Integer svcId = GroundsWorklet.getInstance().getContext().getSvcId();

        RequestTableModel model = (RequestTableModel) this.requestTable.getModel();

        model.setServiceId(svcId);

        WorkRequest.Status status =
                (WorkRequest.Status) this.statusComboBox.getSelectedItem();

        model.setStatus(status);

        long now = System.currentTimeMillis();

        long start = getStart(now);
        model.setStart(start);

        long end = getEnd(now);
        model.setEnd(end);

        model.setUser((User) this.userComboBox.getSelectedItem());

        model.refresh();

        int count = model.getRowCount();

        if (count == 0) {
            this.editButton.setEnabled(false);
        } else {
            this.editButton.setEnabled(true);
        }

        this.entriesLabel.setText(count + "");
        if (interact) {
            if (count == 0) {
                JOptionPane.showMessageDialog(frame, "No work requests found.",
                        "Grounds", JOptionPane.INFORMATION_MESSAGE);
            }
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        statusComboBox = new javax.swing.JComboBox();
        jLabel2 = new javax.swing.JLabel();
        ageComboBox = new javax.swing.JComboBox();
        userComboBox = new javax.swing.JComboBox();
        jLabel3 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        requestTable = new javax.swing.JTable();
        refreshButton = new javax.swing.JButton();
        addButton = new javax.swing.JButton();
        editButton = new javax.swing.JButton();
        deleteButton = new javax.swing.JButton();
        byeButton = new javax.swing.JButton();
        jLabel4 = new javax.swing.JLabel();
        entriesLabel = new javax.swing.JLabel();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        printNewRevisedMenuItem = new javax.swing.JCheckBoxMenuItem();
        printMenuItem = new javax.swing.JMenuItem();
        printAllMenuItem = new javax.swing.JCheckBoxMenuItem();
        jMenu3 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenu4 = new javax.swing.JMenu();
        refreshMenuItem = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        hostInfoMenuItem = new javax.swing.JMenuItem();
        aboutMenuItem = new javax.swing.JMenuItem();
        jMenu5 = new javax.swing.JMenu();
        gauntletButton = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setBackground(new java.awt.Color(0, 0, 0));

        jPanel1.setBackground(new java.awt.Color(221, 221, 221));

        jLabel1.setFont(new java.awt.Font("Comic Sans MS", 0, 14));
        jLabel1.setText("Status:");

        statusComboBox.setFont(new java.awt.Font("Tahoma", 0, 12));
        statusComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                statusComboBoxItemStateChanged(evt);
            }
        });

        jLabel2.setFont(new java.awt.Font("Comic Sans MS", 0, 14));
        jLabel2.setText("Age:");

        ageComboBox.setFont(new java.awt.Font("Tahoma", 0, 12));
        ageComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "<= 24 hours", "<= 1 week", "<=30 days", ">30 & <=60 days", ">60 & <= 90 days", ">90 & <= 180 days", ">180 <= 365 days", ">1 year", " " }));
        ageComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                ageComboBoxItemStateChanged(evt);
            }
        });
        ageComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ageComboBoxActionPerformed(evt);
            }
        });

        userComboBox.setFont(new java.awt.Font("Tahoma", 0, 12));
        userComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                userComboBoxItemStateChanged(evt);
            }
        });

        jLabel3.setFont(new java.awt.Font("Comic Sans MS", 0, 14));
        jLabel3.setText("User:");

        jScrollPane1.setBackground(new java.awt.Color(221, 221, 221));

        requestTable.setModel(new org.workplicity.marist.grounds.ui.table.RequestTableModel( ));
        jScrollPane1.setViewportView(requestTable);

        refreshButton.setBackground(new java.awt.Color(231, 231, 231));
        refreshButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/refresh2.png"))); // NOI18N
        refreshButton.setToolTipText("Click to recycle the display.");
        refreshButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                refreshButtonActionPerformed(evt);
            }
        });

        addButton.setBackground(new java.awt.Color(231, 231, 231));
        addButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/add2.png"))); // NOI18N
        addButton.setToolTipText("Click to add a new work request.");
        addButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addButtonActionPerformed(evt);
            }
        });

        editButton.setBackground(new java.awt.Color(231, 231, 231));
        editButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/drill2.png"))); // NOI18N
        editButton.setToolTipText("Click to edit a work request.");
        editButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editButtonActionPerformed(evt);
            }
        });

        deleteButton.setBackground(new java.awt.Color(231, 231, 231));
        deleteButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/remove2.png"))); // NOI18N
        deleteButton.setToolTipText("Click this to delete a work request.");
        deleteButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteButtonActionPerformed(evt);
            }
        });

        byeButton.setBackground(new java.awt.Color(231, 231, 231));
        byeButton.setFont(new java.awt.Font("Tahoma", 1, 12));
        byeButton.setForeground(new java.awt.Color(102, 51, 255));
        byeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/bye.png"))); // NOI18N
        byeButton.setToolTipText("Click to logoff.");
        byeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                byeButtonActionPerformed(evt);
            }
        });

        jLabel4.setFont(new java.awt.Font("Comic Sans MS", 0, 14));
        jLabel4.setText("Entries:");

        entriesLabel.setFont(new java.awt.Font("Comic Sans MS", 1, 14));
        entriesLabel.setText("0");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(refreshButton, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 68, Short.MAX_VALUE)
                        .addComponent(jLabel4)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(entriesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(93, 93, 93)
                        .addComponent(addButton, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(editButton, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(deleteButton, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(byeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                        .addGap(8, 8, 8)
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(statusComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(ageComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jLabel3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(userComboBox, 0, 156, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 563, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(ageComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(userComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3)
                    .addComponent(jLabel1)
                    .addComponent(statusComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 241, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                        .addComponent(byeButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(deleteButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(editButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(addButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addComponent(refreshButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 29, Short.MAX_VALUE)
                    .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jLabel4)
                        .addComponent(entriesLabel)))
                .addContainerGap())
        );

        jMenuBar1.setBackground(new java.awt.Color(221, 221, 221));

        jMenu1.setBackground(new java.awt.Color(221, 221, 221));
        jMenu1.setText("File");
        jMenu1.setFont(new java.awt.Font("Comic Sans MS", 0, 14));

        printNewRevisedMenuItem.setFont(new java.awt.Font("Tahoma", 0, 14));
        printNewRevisedMenuItem.setText("Print New & Revised...");
        printNewRevisedMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                printNewRevisedMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(printNewRevisedMenuItem);

        printMenuItem.setFont(new java.awt.Font("Tahoma", 0, 14));
        printMenuItem.setText("Print Selected...");
        printMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                printMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(printMenuItem);

        printAllMenuItem.setFont(new java.awt.Font("Tahoma", 0, 14));
        printAllMenuItem.setText("Print All...");
        printAllMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                printAllMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(printAllMenuItem);

        jMenuBar1.add(jMenu1);

        jMenu3.setBackground(new java.awt.Color(221, 221, 221));
        jMenu3.setText("Search");
        jMenu3.setFont(new java.awt.Font("Comic Sans MS", 0, 14));

        jMenuItem1.setFont(new java.awt.Font("Comic Sans MS", 0, 14));
        jMenuItem1.setText("By request id...");
        jMenu3.add(jMenuItem1);

        jMenuBar1.add(jMenu3);

        jMenu4.setBackground(new java.awt.Color(221, 221, 221));
        jMenu4.setText("View");
        jMenu4.setFont(new java.awt.Font("Comic Sans MS", 0, 14));

        refreshMenuItem.setFont(new java.awt.Font("Comic Sans MS", 0, 14));
        refreshMenuItem.setText("Refresh");
        refreshMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                refreshMenuItemActionPerformed(evt);
            }
        });
        jMenu4.add(refreshMenuItem);

        jMenuBar1.add(jMenu4);

        jMenu2.setBackground(new java.awt.Color(221, 221, 221));
        jMenu2.setText("Help");
        jMenu2.setFont(new java.awt.Font("Comic Sans MS", 0, 14));

        hostInfoMenuItem.setFont(new java.awt.Font("Comic Sans MS", 0, 14)); // NOI18N
        hostInfoMenuItem.setText("Host info...");
        hostInfoMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                hostInfoMenuItemActionPerformed(evt);
            }
        });
        jMenu2.add(hostInfoMenuItem);

        aboutMenuItem.setFont(new java.awt.Font("Tahoma", 0, 12));
        aboutMenuItem.setText("About...");
        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutMenuItemActionPerformed(evt);
            }
        });
        jMenu2.add(aboutMenuItem);

        jMenuBar1.add(jMenu2);

        jMenu5.setText("Tools");
        jMenu5.setFont(new java.awt.Font("Comic Sans MS", 0, 14)); // NOI18N

        gauntletButton.setFont(new java.awt.Font("Comic Sans MS", 0, 14)); // NOI18N
        gauntletButton.setText("Gauntlet");
        gauntletButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                gauntletButtonActionPerformed(evt);
            }
        });
        jMenu5.add(gauntletButton);

        jMenuBar1.add(jMenu5);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                GroundsRequest request = new GroundsRequest();

                request.setStatus(Helper.whoAmI(context).getId(), WorkRequest.Status.OPEN);

                Integer svcId = context.getSvcId();
                request.setServiceId(svcId);

                request.setUpdateDate(new WorkDate());

                String svcName = GroundsHelper.getSvcName(svcId);

                Logger.log("creating " + request.getStatus() + " order for service=" + svcName + " svcid=" + svcId);

                WorkRequest.Status status =
                        (WorkRequest.Status) frame.statusComboBox.getSelectedItem();

                EditOrderDialog2 dialog = new EditOrderDialog2(frame, "Create", request, status);

                dialog.setVisible(true);
            }
        });
    }//GEN-LAST:event_addButtonActionPerformed

    private void editButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editButtonActionPerformed
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                editRequest(requestTable.getSelectedRow());
            }
        });
    }//GEN-LAST:event_editButtonActionPerformed

    private void editRequest(int row) {
        if (row == -1)
            return;

        GroundsWorklet.getInstance().getServicesCache().refresh();
        GroundsWorklet.getInstance().getWorkSlatesCache().refresh();
        GroundsWorklet.getInstance().getUsersCache().refresh();

        RequestTableModel model = (RequestTableModel) frame.requestTable.getModel();

        GroundsRequest request = model.getRow(row).getRequest();

        if (!(request instanceof GroundsRequest)) {
            String msg = "This order is not a grounds\n";
            msg += "work request and cannot be edited.";

            JOptionPane.showMessageDialog(frame, msg,
                    "Grounds", JOptionPane.ERROR_MESSAGE);
            return;
        }

        WorkRequest.Status status =
                (WorkRequest.Status) frame.statusComboBox.getSelectedItem();

        EditOrderDialog2 dialog = new EditOrderDialog2(frame, "Update", (GroundsRequest) request, status);

        dialog.setVisible(true);
    }

    private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteButtonActionPerformed
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                int row = requestTable.getSelectedRow();

                if (row == -1) {
                    return;
                }

                String msg = "This operation will permanently delete";
                msg += "\nthis work request. Proceed?";

                int n = JOptionPane.showConfirmDialog(
                        frame,
                        msg,
                        "Confirm",
                        JOptionPane.YES_NO_OPTION);

                if (n == 1) {
                    return;
                }

                WorkRequest.Status status =
                        (WorkRequest.Status) frame.statusComboBox.getSelectedItem();

                if (status == WorkRequest.Status.RECURRING || status == WorkRequest.Status.PENDING) {
                    deleteEvent();
                } else {
                    deleteRequest();
                }
            }
        });
    }//GEN-LAST:event_deleteButtonActionPerformed

    private void refreshMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshMenuItemActionPerformed
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                GroundsWorklet.getInstance().getServicesCache().refresh();
                GroundsWorklet.getInstance().getWorkSlatesCache().refresh();
                GroundsWorklet.getInstance().getUsersCache().refresh();

                loadOrders(allowPopups);
            }
        });
    }//GEN-LAST:event_refreshMenuItemActionPerformed

    private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
//                User user = Repository.whoAmI(context);
//                user.setStamp(new WorkDate(System.currentTimeMillis()));

                refresh();
            }
        });
    }//GEN-LAST:event_refreshButtonActionPerformed

    private void byeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_byeButtonActionPerformed
        winClose();

        dispose();
    }//GEN-LAST:event_byeButtonActionPerformed

    private void statusComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_statusComboBoxItemStateChanged
        // Combo boxes send two events: one for the deselected item
        // and one for the selected one -- we only want the selected one
        if (evt.getStateChange() == ItemEvent.DESELECTED)
            return;

        if(!allowPopups)
            return;

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                refresh();
            }
        });
    }//GEN-LAST:event_statusComboBoxItemStateChanged

    private void hostInfoMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hostInfoMenuItemActionPerformed
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                WorkletContext context = GroundsWorklet.getInstance().getContext();

                Host host = (Host) context.read(Resources.TAG_HOST);

                String msg = "Connected via \n" + host;

                JOptionPane.showMessageDialog(frame, msg,
                        "Netslate", JOptionPane.INFORMATION_MESSAGE);
            }
        });
    }//GEN-LAST:event_hostInfoMenuItemActionPerformed

    private void ageComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ageComboBoxActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_ageComboBoxActionPerformed

    private void ageComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_ageComboBoxItemStateChanged
//        // Combo boxes send two events: one for the deselected item
//        // and one for the selected one -- we only want the selected one
//        if(evt.getStateChange() == ItemEvent.DESELECTED)
//            return;
//
//         SwingUtilities.invokeLater(new Runnable() {
//            @Override
//            public void run() {
//                refresh();
//            }
//        });
    }//GEN-LAST:event_ageComboBoxItemStateChanged

    private void userComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_userComboBoxItemStateChanged
//        // Combo boxes send two events: one for the deselected item
//        // and one for the selected one -- we only want the selected one
//        if(evt.getStateChange() == ItemEvent.DESELECTED)
//            return;
//
//        SwingUtilities.invokeLater(new Runnable() {
//            @Override
//            public void run() {
//                refresh();
//            }
//        });
    }//GEN-LAST:event_userComboBoxItemStateChanged

    private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutMenuItemActionPerformed
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                String msg = "Grounds plugin beta release 3\n(c) Workplicity contributors";

                JOptionPane.showMessageDialog(frame, msg,
                        "Netslate", JOptionPane.INFORMATION_MESSAGE);
            }
        });
    }//GEN-LAST:event_aboutMenuItemActionPerformed

    private void printMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_printMenuItemActionPerformed
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                // TODO add your handling code here:
                // Get the selected request
//                int row = requestTable.getSelectedRow();

                int[] rows = requestTable.getSelectedRows();

                if (rows.length == 0) {
                    JOptionPane.showMessageDialog(frame, "Please select one or more work requests to print.",
                            "Grounds", JOptionPane.INFORMATION_MESSAGE);
                    return;
                }

                sendToPrinter(rows);
            }
        });

    }//GEN-LAST:event_printMenuItemActionPerformed

    private void sendToPrinter(int[] rows) {
        // Get the current table showing on the display
        RequestTableModel model = (RequestTableModel) requestTable.getModel();

        // Get the status drop-down as this affects how we complete the requests
        WorkRequest.Status status = (WorkRequest.Status) this.statusComboBox.getSelectedItem();

        // Initialize the buffers
        ArrayList<GroundsRequest> requests = new ArrayList<GroundsRequest>();
        ArrayList<WorkSlate> workslates = new ArrayList<WorkSlate>();
        ArrayList<Integer> numsUsers = new ArrayList<Integer>();

        ArrayList<User> users = GroundsWorklet.getInstance().getUsersCache().getCache();

        // Pre-process each row's request
        for (int i = 0; i < rows.length; i++) {
            int row = rows[i];

            GroundsRequest request = model.getRow(row).getRequest();

            WorkSlate ws = null;

            if(status == WorkRequest.Status.PENDING || status == WorkRequest.Status.RECURRING) {
                // If this is a pending or recurring request, get
                // its event and complete the request
                Integer eventId = request.getFutureId();

                // Get the request
                Event event =
                    (Event) Helper.fetch(NetTask.REPOS_FUTURES, eventId, GroundsWorklet.getInstance().getContext());

                // Use the template for the request and
                // clone it since we are changing it and
                // DONT want to affect the orginal version
                request = (GroundsRequest) Helper.copy(event.getTemplate());

                request.setUpdateUserId(event.getUpdateUserId());
                request.setId(event.getId());
                request.setFutureId(event.getId());
                
                WorkDate nextFireDate = GroundsHelper.getNextFireDate((Recurring) event);
                request.setAssignedDate(nextFireDate);

                ws = GroundsHelper.getWorkSlate(event.getWorkSlateId());
            }
            else
                ws = GroundsHelper.getWorkSlate(request);

            int nusers = 0;

            if (ws != null) {
                for (User auser : users) {
                    for (Integer id : auser.getWorkSlateList()) {
                        if (id.equals(ws.getId())) {
                            nusers++;
                        }
                    }
                }
            }

            requests.add(request);

            workslates.add(ws);

            numsUsers.add(nusers);
        }

        startPrinter(requests, workslates, numsUsers);
    }

    private void startPrinter(ArrayList<GroundsRequest> requests, ArrayList<WorkSlate> workslates, ArrayList<Integer> numsUsers) {
        //Initialize
        PrinterJob job = PrinterJob.getPrinterJob();
        Book book = new Book();

        //Round up, of course then cast to int to calculate the number of pages to be printed
        int numPages = (int) Math.ceil(requests.size()/3.0);

        //Set the margins of the paper to be the full size of the page
        Paper paper = new Paper();
        paper.setImageableArea(0,0,612,792);
        PageFormat pf = new PageFormat();
        pf.setPaper(paper);

        //Render the pages to the book and then pass them to the job
        book.append(new MainPrinter(this, requests, workslates, numsUsers ), pf, numPages);
        job.setPageable(book);

        //Display the print dialog and if user clicks ok, print.
        boolean doPrint = job.printDialog();
//        boolean doPrint = job.printDialog(aset);
        if (doPrint) {
            try {
                job.print();
            } catch (PrinterException e) {
                e.printStackTrace();
            }
        }
    }

    private void printAllMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_printAllMenuItemActionPerformed
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                int[] rows = new int[requestTable.getRowCount()];

                for(int row=0; row < requestTable.getRowCount(); row++)
                    rows[row] = row;

                sendToPrinter(rows);
            }
        });
    }//GEN-LAST:event_printAllMenuItemActionPerformed

    private void printNewRevisedMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_printNewRevisedMenuItemActionPerformed
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                RequestTableModel model = (RequestTableModel) requestTable.getModel();

                ArrayList<Integer> revisedNewRows = new ArrayList<Integer>( );

                for(int row=0; row < requestTable.getRowCount(); row++) {
                    String state = (String) model.getValueAt(row, RequestTableModel.STATE);

                    if(state.contains("New") || state.contains("Revised")) {
                        revisedNewRows.add(row);
                    }
                }

                // Transfer the rows array list info to the integer array
                // (Note: ArrayList doesn't provide a method to do this.)
                int[] rows = new int[revisedNewRows.size()];

                for(int i=0; i < revisedNewRows.size(); i++)
                    rows[i] = revisedNewRows.get(i);

                sendToPrinter(rows);
            }
        });
    }//GEN-LAST:event_printNewRevisedMenuItemActionPerformed

    private void gauntletButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gauntletButtonActionPerformed
         SwingUtilities.invokeLater(new Runnable(){
             public void run(){
                
                 try {
                     
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                    //Logger.getLogger(UI.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InstantiationException ex) {
                    //Logger.getLogger(UI.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalAccessException ex) {
                    //Logger.getLogger(UI.class.getName()).log(Level.SEVERE, null, ex);
                } catch (UnsupportedLookAndFeelException ex) {
                    //Logger.getLogger(UI.class.getName()).log(Level.SEVERE, null, ex);
                }

                GauntletDialog dialog = new GauntletDialog(new javax.swing.JFrame(), true);
                dialog.addWindowListener(new java.awt.event.WindowAdapter() {
                    @Override
                    public void windowClosing(java.awt.event.WindowEvent e) {
                        System.exit(0);
                    }
                });
                dialog.setVisible(true);
             }



         });
    }//GEN-LAST:event_gauntletButtonActionPerformed

    private void refresh() {
        GroundsWorklet.getInstance().getServicesCache().refresh();
        GroundsWorklet.getInstance().getWorkSlatesCache().refresh();
        GroundsWorklet.getInstance().getUsersCache().refresh();

        loadOrders(allowPopups);
    }

    private void deleteRequest() {
        // Get the selected request
        int row = this.requestTable.getSelectedRow();

        RequestTableModel model = (RequestTableModel) this.requestTable.getModel();

        GroundsRequest request = model.getRow(row).getRequest();

        WorkSlate ws = GroundsHelper.getWorkSlate(request);

        if (ws != null) {
            if (!deleteInWorkSlate(request, ws)) {
                String msg = "Delete failed updating work slate id = " + ws.getId() + "!";

                JOptionPane.showMessageDialog(frame, msg,
                        "Grounds", JOptionPane.ERROR_MESSAGE);

                return;
            }
        }

        if (!Helper.delete(request, NetTask.REPOS_CLEARINGHOUSE, context)) {
            String msg = "Delete failed to remove request id = " + request.getId() + "!";

            JOptionPane.showMessageDialog(frame, msg,
                    "Grounds", JOptionPane.ERROR_MESSAGE);
            return;
        }

        model.remove(row);

        model.fireTableDataChanged();

        JOptionPane.showMessageDialog(frame, "Request id=" + request.getId() + " successfully deleted.",
                "Grounds", JOptionPane.INFORMATION_MESSAGE);
    }

    private void deleteEvent() {
        String msg = "This operation will permanently delete";
        msg += "\nALL forward requests in the series. Proceed?";

        int n = JOptionPane.showConfirmDialog(
                frame,
                msg,
                "Confirm",
                JOptionPane.YES_NO_OPTION);

        if (n == 1) {
            return;
        }

        // Get the selected request
        int row = this.requestTable.getSelectedRow();

        // Retrieve the event
        RequestTableModel model = (RequestTableModel) this.requestTable.getModel();
        GroundsRequest request = model.getRow(row).getRequest();

        int futureId = request.getId();

        Recurring recurring = (Recurring) Helper.fetch(NetTask.REPOS_FUTURES, futureId, context);

        if (recurring == null) {
            JOptionPane.showMessageDialog(frame, "Event id = " + futureId + " not found!",
                    "Grounds", JOptionPane.ERROR_MESSAGE);
            return;
        }

        // Remove the event
        boolean successful = Helper.delete(recurring, NetTask.REPOS_FUTURES, context);

        if (!successful) {
            JOptionPane.showMessageDialog(frame, "Failed to delete event id = " + futureId + ".",
                    "Grounds", JOptionPane.ERROR_MESSAGE);

            return;
        }

        model.remove(row);

        model.fireTableDataChanged();

        JOptionPane.showMessageDialog(frame, "Event id = " + futureId + " successfully deleted.",
                "Grounds", JOptionPane.INFORMATION_MESSAGE);

        return;
    }

    private boolean deleteInWorkSlate(WorkRequest request, WorkSlate workSlate) {
        Integer rid = null;

        for (Integer keyId : workSlate.getWorkRequestList()) {
            if (keyId.equals(request.getId())) {
                rid = keyId;
                break;
            }
        }

        if (rid == null) {
            return false;
        }

        workSlate.getWorkRequestList().remove(rid);

        boolean success =
                Helper.insert(workSlate, NetTask.REPOS_WORKSLATES, context);

        return success;
    }
    private final static long ONE_DAY = 24 * 60 * 60 * 1000;

    private long getStart(long now) {
        switch (this.ageComboBox.getSelectedIndex()) {
            case 0: // <= 24 hours
                return now - ONE_DAY;

            case 1: // <= 1 week
                return now - 7 * ONE_DAY;

            case 2: // <= 30 days
                return now - 30 * ONE_DAY;

            case 3: // >30 & <= 60 days
                return now - 60 * ONE_DAY;

            case 4: // >= 60 & < 90 days
                return now - 90 * ONE_DAY;

            case 5: // >= 90 & < 180 days
                return now - 180 * ONE_DAY;

            case 6: // >= 180 & < 365 days
                return now - 365 * ONE_DAY;

            case 7: // > 1 year
                return 0;
        }

        return now;
    }

    private long getEnd(long now) {
        switch (this.ageComboBox.getSelectedIndex()) {
            case 2: // <= 30 days
                return now;

            case 3: // >30 & <= 60 days
                return now - (30 + 1) * ONE_DAY;

            case 4: // >= 60 & < 90 days
                return now - (60 + 1) * ONE_DAY;

            case 5: // >= 90 & < 180 days
                return now - (90 + 1) * ONE_DAY;

            case 6: // >= 180 & < 365 days
                return now - 180 * ONE_DAY;

            case 7: // > 1 year
                return now - (long) (365.25 * ONE_DAY);
        }

        return now;
    }

    private void winClose() {
        Helper.logout(user, context);

        Logger.log("logged out user = '" + user + "'");
    }

    private static void launchForDebug(String logn, String passwd, String url, Integer svcId) {
        // Set the url to access the server
        NetTask.setUrlBase(url);

        // Get a context a populate it with the svc id and host info, if we needed it
        WorkletContext ctx = WorkletContext.getInstance();

        ctx.setSvcId(svcId);

        ctx.publish(Resources.TAG_HOST, new Host(url));

        // Login
        if (!Helper.login(logn, passwd, ctx)) {
            Logger.log("login failed for logn = " + logn + " passwd = " + passwd + " url = " + url);
            return;
        }

        // Now that the login has suceeded, the context is now
        // ready as if we came through the JNLP, so let's
        // finish the job and (literally) go that route by invoking
        // "go" on the context
        Resources.logoSmall = new ImageIcon("/logo3.png");

        GroundsWorklet worklet = new GroundsWorklet();

        worklet.go(ctx);
    }

    private static void launchForJNLP() {
        try {
            javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            Logger.log(e.toString());
        }

        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                final GroundsFrame frame = new GroundsFrame();

                frame.setLocationByPlatform(true);

                frame.addWindowListener(new java.awt.event.WindowAdapter() {

                    @Override
                    public void windowClosing(java.awt.event.WindowEvent e) {
//                        System.exit(0);
                        frame.winClose();

                        System.exit(0);
                    }
                });

                frame.setVisible(true);
            }
        });
    }

    /**
     * @param args the command line arguments
     */
    public static void main(final String args[]) {
        Logger.log("starting grounds frame...");

        if (args != null) {
            String logn = args[0];

            String passw = args[1];

            String url = args[2];

            Integer svcId = Integer.parseInt(args[3]);

            launchForDebug(logn, passw, url, svcId);
        } else {
            launchForJNLP();
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem aboutMenuItem;
    private javax.swing.JButton addButton;
    private javax.swing.JComboBox ageComboBox;
    private javax.swing.JButton byeButton;
    private javax.swing.JButton deleteButton;
    private javax.swing.JButton editButton;
    private javax.swing.JLabel entriesLabel;
    private javax.swing.JMenuItem gauntletButton;
    private javax.swing.JMenuItem hostInfoMenuItem;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenu jMenu4;
    private javax.swing.JMenu jMenu5;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JCheckBoxMenuItem printAllMenuItem;
    private javax.swing.JMenuItem printMenuItem;
    private javax.swing.JCheckBoxMenuItem printNewRevisedMenuItem;
    private javax.swing.JButton refreshButton;
    private javax.swing.JMenuItem refreshMenuItem;
    private javax.swing.JTable requestTable;
    private javax.swing.JComboBox statusComboBox;
    private javax.swing.JComboBox userComboBox;
    // End of variables declaration//GEN-END:variables
}
